// -----------------------------
// Author: 		Dhaenens Gert	
// Creation: 	11/19/2014 8:50:50 PM				
// -----------------------------

#include "SceneLoader.h"

#include "Application.h"

#include "Thread.h"

#include "MeshActor.h"
#include "LightActor.h"
#include "Cube.h"
#include "Camera.h"

#include "RenderManager.h"
#include "RenderPass.h"

#include "DefaultMaterial.h"

struct ThreadArgs
{
	Scene*			lpScene;
	Application*	lpApp;
};
void SceneLoader::ThreadCallback(Thread* lpThread, void* lpArgs)
{
	// Interpret the Args
	ThreadArgs* lpThreadArgs = reinterpret_cast<ThreadArgs*>(lpArgs);
	// Seed the RNG
	Math::SetSeed(0);
	// Load the Scene
	lpThreadArgs->lpScene->Load(lpThreadArgs->lpApp);
	// Delete the Args
	delete lpThreadArgs;

}

SceneLoader::SceneLoader(const TString& Name, Scene* lpSceneToLoad)
	: Scene(Name)
	, m_lpLoadingThread(nullptr)
	, m_lpSceneToLoad(lpSceneToLoad)
	, m_Rotation(0.0f)
	, m_RotationSpeed(50.0f)
{
}

SceneLoader::~SceneLoader()
{
	delete m_lpLoadingThread;
}

void SceneLoader::OnActivate(Application* lpApp)
{
	Scene::OnActivate(lpApp);

	// Disable Skybox Pass
	RenderPass* lpSkyboxPass = lpApp->GetRenderer()->GetRenderPass("Skybox");
	if (lpSkyboxPass)
		lpSkyboxPass->SetEnabled(false);

	// Start the Thread
	Log::WriteLine(_T("[INFO]\t\tLoading Scene \"%s\"."), m_lpSceneToLoad->GetName().c_str());
	ThreadArgs* lpArgs = new ThreadArgs();
	lpArgs->lpApp = lpApp;
	lpArgs->lpScene = m_lpSceneToLoad;
	m_lpLoadingThread->Start(ThreadCallback, lpArgs);
}
void SceneLoader::OnDeactivate(Application* lpApp)
{
	Scene::OnDeactivate(lpApp);

	// Delete itself
	delete this;
}
void SceneLoader::OnGUI(Application* lpApp, IRenderTarget2D* lpTarget)
{
	Scene::OnGUI(lpApp, lpTarget);
}

void SceneLoader::Load(Application* lpApp)
{
	Scene::Load(lpApp);

	// Create the Rotating Cube
	MeshActor* lpCubeActor = new MeshActor(_T("Cube"));
	Mesh* lpCubeMesh = new Cube(lpApp->GetRenderer(), 1.0f);
	Material* lpCubeMaterial = new DefaultMaterial(lpApp, Color::White, Color(0.6f, 0.6f, 0.6f), 1.0f, 0.0f);
	lpCubeActor->SetMesh(lpCubeMesh);
	lpCubeActor->SetMaterial(lpCubeMaterial);
	lpCubeMaterial->Release();
	lpCubeMesh->Release();
	this->AddActor(lpCubeActor);

	// Setup the Camera
	Camera* lpCamera = new Camera(_T("Camera"));
	lpCamera->SetPosition(Vector3(0.0f, 0.0f, -5.0f));
	lpCamera->SetLookAt(Vector3(0.0f, 0.0f, 0.0f));
	this->SetCamera(lpCamera, false, true);

	// Create a Light
	LightActor* lpLight = new LightActor(_T("Sun"), LightActor::Directional);
	lpLight->SetPosition(Vector3(-5.0f, 5.0f, -5.0f));
	lpLight->SetLookAt(Vector3(0.0f, 0.0f, 0.0f));
	AddActor(lpLight);

	// Create the Thread
	m_lpLoadingThread = new Thread();
}
void SceneLoader::Update(Application* lpApp, Float deltaTime)
{
	Scene::Update(lpApp, deltaTime);

	// Check if the Scene is Still Loading
	// If so, keep drawing the Loading Scene
	
	if (m_lpLoadingThread->IsRunning())
	{
		m_Rotation += m_RotationSpeed * deltaTime;

		Matrix rotX = Matrix::RotationX(Math::Deg2Rad(45.0f));
		Matrix rotY = Matrix::RotationY(Math::Deg2Rad(m_Rotation));
		Matrix rotZ = Matrix::RotationZ(Math::Deg2Rad(45.0f));
		Matrix finalRot = rotZ * rotX * rotY;

		MeshActor* lpCube = (MeshActor*) FindActor(_T("Cube"));
		lpCube->SetRotation(finalRot);
		
	}
	// Else switch the Scene
	else
	{
		// Enable Skybox Pass
		RenderPass* lpSkyboxPass = lpApp->GetRenderer()->GetRenderPass("Skybox");
		if (lpSkyboxPass)
			lpSkyboxPass->SetEnabled(true);

		lpApp->SetScene(m_lpSceneToLoad);
	}
}